#include "cmac.h"

void CMAC_GenerateSecKeys(const uint64_t *R, uint64_t *K1, uint64_t *K2){
    uint64_t tmp;
    uint64_t B = {0};

    B |= 0b11011;

    *K1 = *R;
    *K1 = (*K1<<1) | (*K1 >> 63);
    if (*R & f_bit)
        *K1 ^= B;

    *K2 = *K1;
    *K2 = (*K2 << 1) | (*K2 >> 63);
    if (*K1 & f_bit)
        *K2 ^= B;
}


void Proc2(uint64_t *P){
    *P = (*P<<1) | 1;
    while ((*P & f_bit) == 0)
        *P <<= 1;
}


void CMAC_ReturnHash(uint8_t ind, uint64_t *P, uint64_t *MAC, uint64_t *Cq_1,uint64_t *Key, uint8_t s){
    if ((P[ind] & f_bit) == 0)
        Proc2(P+ind);

    uint64_t res = P[ind]^(*Cq_1)^(*Key);
    Magma_Encript(&res, MAC);

    uint64_t mask = 0xFFFFFFFFFFFFFFFF;
    mask <<= (64-s);

    uint64_t tmp = *MAC;

    tmp &= mask;
    tmp >>= (64-s);
    *MAC = tmp;
}


void CMAC_Iter(uint8_t count_block, uint64_t *P, uint64_t *MAC, uint64_t *Cq_1){
    uint64_t C = *MAC;
    uint64_t res_oper = 0;
    for (int i = 0; i < count_block-1; ++i){
        res_oper = P[i]^C;
        Magma_Encript(&res_oper, &C);
    }

    *Cq_1 = C;
    res_oper = P[count_block-1]^(*Cq_1);
    Magma_Encript(&res_oper, MAC);
}